package com.triple.triplerpc.fault.retry;

import com.github.rholder.retry.*;
import com.triple.triplerpc.model.RpcResponse;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 固定时间间隔策略实现类 - 重试策略
 */
@Slf4j
public class FixedIntervalRetryStrategy implements RetryStrategy {

    /**
     * 重试机制封装方法
     * 该方法使用Retryer来执行给定的Callable任务，并在任务失败时根据预设的策略进行重试
     *
     * @param callable 需要执行的任务，一个实现了Callable接口的实例
     * @return RpcResponse 执行任务后的响应结果
     * @throws ExecutionException 如果执行过程中抛出了异常
     * @throws RetryException 如果重试策略决定不再重试时抛出
     */
    @Override
    public RpcResponse doRetry(Callable<RpcResponse> callable) throws ExecutionException, RetryException {
        System.out.println(" >>> 当前采用的重试机制 - 固定时间间隔");
        // 构建一个Retryer实例, 用于执行可能需要重试的任务
        Retryer<RpcResponse> retryer = RetryerBuilder.<RpcResponse>newBuilder()
                .retryIfExceptionOfType(Exception.class) // 指定当发生Exception类型异常时进行重试
                .withWaitStrategy(WaitStrategies.fixedWait(3L, TimeUnit.SECONDS)) // 指定固定等待的时间
                .withStopStrategy(StopStrategies.stopAfterAttempt(3)) // 重试三次后放弃
                .withRetryListener(new RetryListener() { // 每次重试时, 除了再次执行任务外, 打印当前的重试次数
                    @Override
                    public <V> void onRetry(Attempt<V> attempt) {
                        log.info("重试次数 {}", attempt.getAttemptNumber());
                    }
                })
                .build();
        // 使用Retryer执行给定的Callable任务
        return retryer.call(callable);
    }

}
